import importlib
import xml.dom.minidom
import codecs

global trace_stream
trace_stream = open("/dev/null","w")

def set_trace_stream(s) :
    global trace_stream;
    trace_stream = s

import td_encrypt
import td_geocode

class TrailDataImporter :
    def __init__(self,name) :
        self.name = name
        self.trail = importlib.import_module("input_"+name).trail
        self.geocodeForMissingCoordinates()
    def geocodeCollectionIfPresent(self,owner,cname) :
        try :
            for c_item in owner[cname] :
                (c_item["latitude"],c_item["longitude"],trace_msg) = \
                    td_geocode.getCoordinatesIfMissing(self.trail["locality"],c_item)
                trace_stream.write(trace_msg+"\n")
                self.geocodeCollectionIfPresent(c_item,"points")
                self.geocodeCollectionIfPresent(c_item,"zones")
        except KeyError: 
            pass
    def geocodeForMissingCoordinates(self) :
        locality = self.trail["locality"]
        trace_stream.write("Geocoding for missing coordinates in trail %s\n"%(locality,))
        self.geocodeCollectionIfPresent(self.trail,"points")
        self.geocodeCollectionIfPresent(self.trail,"zones")
    def toPy(self) :
        INDENT=u"    "
        TRAIL_TEMPLATE = u"trail = {\n%s\n}\n"
        SCALAR_ATTR_TEMPLATE = u"""'%s': u"%s", """
        LIST_ATTR_TEMPLATE = INDENT + SCALAR_ATTR_TEMPLATE + u"\n"
        ZONE_ATTR_TEMPLATE = INDENT + INDENT + INDENT + u"""'%s': u"%s",\n"""
        body = u""
        scalar_attrs_string = u"";
        for aname in ( "locality","version","mode","description") :
            try : scalar_attrs_string += INDENT + SCALAR_ATTR_TEMPLATE%(aname,self.trail[aname].encode('utf-8')) + u"\n"
            except KeyError : pass
        body += scalar_attrs_string
        for aname in ( "zones","points") :
            try :
                list_attrs_string = INDENT + "'" + aname + "': (\n"
                #"""
                for z in self.trail[aname] :
                    list_attrs_string += INDENT + INDENT + u"{\n"
                    for aname2 in ( 'name', 'address','message','url','latitude','longitude','radius_metres') :
                        #try: list_attrs_string += ZONE_ATTR_TEMPLATE%(aname2,z[aname2].decode('utf-8').encode('utf-8'))
                        try: list_attrs_string += ZONE_ATTR_TEMPLATE%(aname2,z[aname2])
                        except KeyError: pass
                        except UnicodeDecodeError:pass
                    list_attrs_string += INDENT + INDENT + u"},\n"
                #"""
                list_attrs_string += INDENT+"),\n"
                body += list_attrs_string
            except KeyError : pass
        f = codecs.open("./generated/input_"+self.name+".py","w",encoding='utf-8',errors='strict')
        f.write(u"# td_%s.py\n# -*- coding:utf-8 -*- \n\n"%(self.name,))
        f.write(TRAIL_TEMPLATE%(body,))
    def createZoneNode(self,doc,z) :
        zoneNode = doc.createElement("zone")
        for attr_name in ( "name", "address", "message", "url",) :
            try : zoneNode.attributes[attr_name]=z[attr_name]
            except KeyError: pass
            except :
                print list(z[attr_name])
                pass
        coordNode = doc.createElement("coordinates")
        for attr_name in ( "latitude", "longitude","radius_metres") :
            try : coordNode.attributes[attr_name]=str(z[attr_name])
            except : pass
        zoneNode.appendChild(coordNode)
        for attr_name in ( "points", "zones" ) :
            try :
                for nestedZone in z[attr_name] :
                    zoneNode.appendChild(self.createZoneNode(doc,nestedZone))
            except: pass
        return zoneNode
    def addEncryptedNodeToTqz(self,attachmentNode,encryptedNodeName,plaintext) :
        pt = plaintext.encode('utf-8')
        # print pt
        ptlen = len(pt)
        ptcrc = '%08x' % (binascii.crc32(pt) & 0xffffffff)
        ct = ''
        while(len(pt)>0) :
            pt_block = pt[0:127]
            pt = pt[128:]
            ct += str(encrypting_key.encrypt(pt_block,""))
        ctlen = len(ct)
        ctcrc = '%08x' % (binascii.crc32(ct) & 0xffffffff)
        ct_b64 = ct.encode("base64")
    def toTqz(self) :
        doc = xml.dom.minidom.getDOMImplementation().createDocument(None, "tw1", None)
        topNode = doc.documentElement
        clearNode = doc.createElement("tw1_plaintext")
        for k in ( "version", "locality", "description", "mode") :
            try : clearNode.attributes[k]=self.trail[k]
            except KeyError : pass
        try : 
            for p in self.trail["points"] :
                zoneNode = self.createZoneNode(doc,p)
                clearNode.appendChild(zoneNode)
        except KeyError: pass
        try :
            for z in self.trail["zones"] :
                zoneNode = self.createZoneNode(doc,z)
                clearNode.appendChild(zoneNode)
        except KeyError: pass
        topNode.appendChild(clearNode)
        xml_text = topNode.toprettyxml(" ","\n","utf-8")
        (ct_b64,ptlen,ptcrc,ctlen,ctcrc) = td_encrypt.encrypt(xml_text) 
        """
        encryptedNode = doc.createElement("tw1_encrypted")
        b64_cryptext_child = doc.createTextNode("\n%s"%ct_b64)
        encryptedNode.appendChild(b64_cryptext_child)
        encryptedNode.attributes["ptlen"] = str(ptlen)
        encryptedNode.attributes["ptcrc"] = str(ptcrc)
        encryptedNode.attributes["ctlen"] = str(ctlen)
        encryptedNode.attributes["ctcrc"] = str(ctcrc)
        topNode.appendChild(encryptedNode)
        """
        f = open("generated/"+self.name+".tqz","w")
        f.write(doc.toprettyxml("    ","\n",'utf-8'))
        f.close()
    def gen_files(self) :
        self.toPy()
        self.toTqz()
 
def td_gen(name) :
    TrailDataImporter(name).gen_files()

